feat(trust): Phase 0 — shared TrustConfig + PlatformTrustConfigs#1266
Conversation
…itive) Defines the shared L2 (scope) + L3 (identity) trust types and pure decision function per the identity-trust-none ADR (#1264). Purely additive: not yet wired into AdapterRouter, changes no runtime behavior. - TrustConfig: L2 (allow_all_channels/allowed_channels/allow_dm, default open) + L3 (allow_all_users/allowed_users, default deny-all) - Decision enum (Allow / DenyScope / DenyIdentity) — only DenyIdentity echoes (request-access UX) - PlatformTrustConfigs registry keyed by platform() (no cross-platform ID bleed) - 11 unit tests covering the L2×L3×DM decision matrix Wiring + removing scattered per-adapter checks lands in Phase 1; the trust-none default flip lands in Phase 3. Refs #1264
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
LGTM ✅ — Purely additive Phase 0 introducing the shared trust decision model. Zero runtime behavior change, correct fail-closed logic, comprehensive test coverage. What This PR DoesIntroduces the L2 (scope) + L3 (identity) trust gate as a shared, pure module in How It Works
Findings
Finding Details🟡 F1: Phase 1 Integration Gap — Batched Dispatch PathsProduction adapters (Discord, Slack, Gateway) in Thread/Lane modes submit events directly to 🟡 F2:
|
- F2: #[non_exhaustive] on Decision (avoid future semver break) - F3: reword DenyScope doc — scope control, not an authorization failure - F6: normalize platform keys to lowercase (case-insensitive registry) - F7: empty sender_id is never identity-allowed (fail-closed, even under allow_all_users) - F5: document new() as canonical constructor; allow_all_* takes precedence - add 3 tests (empty-sender, case-insensitive registry)
|
Thanks — addressed in
Tests: 13/13 trust tests pass, clippy |
|
LGTM ✅ — Clean, well-documented Phase 0 introducing the shared trust gate types with comprehensive tests. What This PR DoesIntroduces the L2 (scope) + L3 (identity) trust decision model as a purely additive, behavior-preserving module. It defines How It Works
Findings
Baseline Check
What's Good (🟢)
|
…ared gate (#1267) * feat(trust): Phase 1 (gateway) — route gateway ingress through shared trust gate Wires the shared L2/L3 gate (#1266) into the unified gateway path: - AdapterRouter gains a PlatformTrustConfigs registry (via with_trust builder — new()'s signature unchanged) + gate_incoming() ingress gate - process_gateway_event now enforces L2/L3 via router.gate_incoming(); should_skip_event keeps only bot-filter + @mention gating (its channel/user checks are neutered in the unified path) - registry built at startup from GATEWAY_* env, keyed per gateway platform Behavior-preserving: registry defaults mirror today's should_skip_event (allow-all default); is_dm passed false so DMs are evaluated as channels exactly as today. Discord/Slack routing + dispatch-path privatization + should_skip_event L2/L3 removal follow in later PRs. Deny-flip is Phase 3. Refs #1264 * docs(trust): add phase-2 TODO for is_dm carrier at gateway gate (review F2) --------- Co-authored-by: chaodu-agent <chaodu-agent@users.noreply.github.com>
Phase 0 of the #1264 trust-pyramid implementation (plan).
Purely additive and behavior-preserving — defines the shared trust types + pure decision function. Not wired into
AdapterRouteryet, so no runtime behavior changes.Decision flow (what this module evaluates)
should_echo()is true only forDenyIdentity— scope denials are silent(the surface simply isn't enabled), identity denials echo the sender their ID so
they can request access.
What's in this PR
crates/openab-core/src/trust.rs:TrustConfig— L2 scope (allow_all_channels/allowed_channels/allow_dm, default open) + L3 identity (allow_all_users/allowed_users, default deny-all)Decisionenum —Allow/DenyScope/DenyIdentity; onlyDenyIdentitytriggers the request-access echo (should_echo())PlatformTrustConfigs— registry keyed byplatform()so a Telegram UID can never satisfy a LINE allowlistdecide(channel_id, is_dm, sender_id)evaluates L2 then L3What's deferred
MessageContext.sender,ChannelRef.is_dm), wiredecide()intohandle_message(), remove scattered checks fromdiscord.rs/slack.rs/gateway.rsTesting
cargo clippy -p openab-core -D warningscleanRefs #1264